﻿using System;
using System.IO;

namespace FlashToolKit
{
	/// <summary>
	/// Builds SWF file from parts using given map file
	/// </summary>
	public class Composer
	{
		private readonly string _filePath;
		private BinaryWriter _writer;

		/// <summary>
		/// Creates new instance of Composer class
		/// </summary>
		/// <param name="mapfilePath">
		/// Full path to map file
		/// </param>
		public Composer(string mapfilePath)
		{
			_filePath = mapfilePath;
		}

		/// <summary>
		/// Composes SWF file using default filename and path
		/// </summary>
		public void Compose()
		{
			StreamReader mapFile;
			try
			{
				mapFile = File.OpenText(_filePath);
			}
			catch (FileNotFoundException)
			{
				return;
			}

			string dirPath = _filePath.Substring(0, _filePath.LastIndexOf('\\'));
			string tgtFileName = dirPath.Substring(dirPath.LastIndexOf('\\') + 1);
			dirPath += "\\";

			var fsTgt = new FileStream(dirPath + tgtFileName + ".swf", FileMode.Create);
			_writer = new BinaryWriter(fsTgt);

			while (!mapFile.EndOfStream)
			{
				WriteToFile(dirPath + mapFile.ReadLine());
			}
			_writer.Write((short)0);
			FixSWFHeader();
			_writer.Close();
			_writer.Dispose();

			mapFile.Close();
		}


		private void WriteToFile (string filePath)
		{
			var fs = File.OpenRead(filePath);
			var reader = new BinaryReader(fs);
			byte[] buff = reader.ReadBytes((int) fs.Length);
			reader.Close();
			FixTagHeader(ref buff);
			_writer.Write(buff);
		}


		private static void FixTagHeader(ref byte[] content)
		{
			if (content.Length < 64 + Constants.TagShortHeaderSize)
			{
				if ((content[0] & Constants.TagHeaderSizeMask) != Constants.TagHeaderSizeMask)
				{
					byte val = content[0];
					val &= Constants.TagHeaderTypeMask;
					val |= (byte)(content.Length - Constants.TagShortHeaderSize);
					content[0] = val;
				}
				else
				{
					byte val = content[0];
					val &= Constants.TagHeaderTypeMask;
					val |= (byte)(content.Length - Constants.TagLongHeaderSize);
					content[0] = val;
					byte[] new_content = new byte[content.Length - 4];
					new_content[0] = content[0];
					new_content[1] = content[1];
					for (int i = 2; i< new_content.Length; i++)
					{
						new_content[i] = content[i + 4];
					}
					content = new_content;
				}
			}
			else
			{
				byte[] val = BitConverter.GetBytes(content.Length - Constants.TagLongHeaderSize);
				for (int i = 0; i < val.Length; i++)
				{
					content[i + 2] = val[i];
				}
				content[0] |= Constants.TagHeaderSizeMask;
			}
			
		}

		private void FixSWFHeader ()
		{
			int len = (int) _writer.BaseStream.Position;
			_writer.Seek(4, SeekOrigin.Begin);
			_writer.Write(len);
			_writer.Seek(0, SeekOrigin.Begin);
			_writer.Write('F');
		}
	}
}
